package ncku.kdd.alg;

import java.util.*;
import java.text.*;
import java.io.*;

import libnetdb.dm.assoc.base.*;
import libnetdb.dm.assoc.dhp.*;
import libnetdb.dm.assoc.dhp.demo.*;
import libnetdb.dm.assoc.util.*;
/**
 * Analyze association rules between labels of the training data.
 * @author ktchuang
 * 這是一個小test
 *
 */

public class LabelAssociationRules {

    RuleSet rs = null;
    String tmp = null;
    NameSpace ns = null;
    private String outfn = null;
    private static ArrayList indexList = new ArrayList();
    {
        IndexManager manager = IndexManager.getInstance();
        Iterator it = manager.builderIterator();
        while(it.hasNext())
            indexList.add(((IndexBuilder)it.next()).createIndex());        
    }

    private static void printUsage(PrintStream ps){
        ps.println("usage: filename support confidence");
    }
    
	public void listRules(Iterator ruleIterator) {
		try {
			BufferedWriter writer = new BufferedWriter(new FileWriter(outfn));
			DecimalFormat format = new DecimalFormat("#0.000");
			while (ruleIterator.hasNext()) {
				Rule rule = (Rule) ruleIterator.next();
				int count = rule.getConsequence().ids.length;
				boolean checkok = false;
				for (int i=0;i<count;i++) {
					if ((ns.getName((rule.getConsequence().ids[i])).charAt(0)) == 'C') {
						checkok=true;
						break;
					}
				}
				if (checkok) {
				  System.out.print(rule.toString());
				  writer.write(rule.toString());			
				  for (int i = 0; i < indexList.size(); ++i) {
					RuleIndex index = (RuleIndex) indexList.get(i);
					System.out
							.print(", " + format.format(index.getIndex(rule)));
					writer.write(", " + format.format(index.getIndex(rule)));
				  }
				  System.out.println();
				  writer.write("\n");
				}
			}
			writer.flush();
			writer.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    public static void listMyRules(Iterator ruleIterator) {
        DecimalFormat format = new DecimalFormat("#0.000");
        while(ruleIterator.hasNext()){
            Rule rule = (Rule) ruleIterator.next();
            System.out.print(rule.toString());

            System.out.println();                   
        }       	
    }
    
    public LabelAssociationRules(String fn, double support, double confidence, String outfn) throws InterruptedException {
        ns = new BasicNameSpace();
        this.outfn = outfn;
        TextInput input = new TextInput(fn, ns);
        DirectBuilder output = new DirectBuilder();
        DHPMiner miner = new DHPMiner(input, output, support);
        miner.addProgressListener(new ConsoleMessenger());
        miner.start();
        miner.join();
        rs = output.getRuleSet();
        rs.setNameSpace(ns);
        
        //listLargeItemset();
        
        //System.out.println("All Rules: ");
        listRules(rs.getRules(support, confidence));
        
        //this.getRecommendLabel(new String[]{"52","A","62","56"}, 0.001, 0.8);
    }
    public void listLargeItemset() {
        Iterator it = rs.ancensterIterator(new Itemset(new int[0]));
        while(it.hasNext()){
            Litemset litemset = (Litemset) it.next();
            System.out.println(
                    rs.toString(litemset) + ": " + litemset.count);
        }
    }
    /**
     * return extended label
     * @param currentLabel
     * @return
     */
    public String[] getRecommendLabel(String[] currentLabel, double sup, double conf) {
    	
    	ArrayList<String> list = new ArrayList<String>();
    	int[] ids = new int[currentLabel.length];
    	for (int i=0;i<ids.length;i++) {
    		ids[i] = ns.getID(currentLabel[i]);
    	}
                      
    	System.out.println("------------------");
        listRules(rs.getRecommendRules(
                ids, sup, conf));
    	return list.toArray(new String[]{""});
    	
    }
    public static void main(String argv[]) throws Exception{
        if(argv.length < 4){
        	System.err.println("Too few arguments");
            printUsage(System.err);
            System.exit(-1);
        }
        
		if(argv.length > 4){
			System.err.println("Too many arguments"); 
			printUsage(System.err);
			System.exit(-1);
		}     
        
        double support = 0;
        double confidence = 0;
       
        
		try {
	        support = Double.parseDouble(argv[1]);
        } catch (NumberFormatException e) {
			System.err.println("format error in argument 'support'");
			return;
		}
		
		try {
			confidence = Double.parseDouble(argv[2]);
		} catch (NumberFormatException e) {
			System.err.println("format error in argument 'confidence'");
			return;
		}		
		
		LabelAssociationRules arMiner = new LabelAssociationRules(argv[0],support,confidence,argv[3]);
    
    }
}
